/*
 *
 *      Copyright (c) 2018-2025, scs All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: scs
 *
 */

package com.zyh.scs.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zyh.scs.admin.api.dto.*;
import com.zyh.scs.admin.api.entity.SysUser;
import com.zyh.scs.admin.api.vo.UserExcelVO;
import com.zyh.scs.admin.service.SysUserService;
import com.zyh.scs.common.core.constant.CommonConstants;
import com.zyh.scs.common.core.exception.ErrorCodes;
import com.zyh.scs.common.core.util.MsgUtils;
import com.zyh.scs.common.core.util.R;
import com.zyh.scs.common.excel.annotation.RequestExcel;
import com.zyh.scs.common.excel.annotation.ResponseExcel;
import com.zyh.scs.common.log.annotation.SysLog;
import com.zyh.scs.common.security.annotation.Inner;
import com.zyh.scs.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author scs
 * @date 2018/12/16
 */
@RestController
@AllArgsConstructor
@RequestMapping("/user")
@Tag(description = "user", name = "用户管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserController {

    private final SysUserService userService;

    /**
     * 获取所有部门公司信息
     *
     * @return 组织架构
     */
    @GetMapping("/getAll")
    @Operation(summary = "获取所有部门公司信息", description = "获取所有部门公司信息")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    public R getAll() {
        return R.ok(userService.getAll());
    }

    /**
     * 重置用户密码
     *
     * @param userDTO
     * @return success/false
     */
    @SysLog("重置用户密码")
    @PostMapping("/password")
    @Operation(summary = "重置用户密码", description = "重置用户密码")
    public R resetUserPassword(@RequestBody UserDTO userDTO) {
        return R.ok(userService.resetPassword(userDTO.getGuid()));
    }

    /**
     * 修改用户密码
     *
     * @param updatePasswordDTO
     * @return success/false
     */
    @SysLog("修改用户密码")
    @PostMapping("/updatePassword")
    @Operation(summary = "修改用户密码", description = "修改用户密码")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R updatePassword(@RequestBody UpdatePasswordDTO updatePasswordDTO) {
        return R.ok(userService.updatePassword(updatePasswordDTO));
    }

    /**
     * 通过ID查询用户信息
     *
     * @param id ID
     * @return 用户信息
     */
    @GetMapping("/details")
    @Operation(summary = "通过ID查询用户信息", description = "通过ID查询用户信息")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    public R user(String id) {
        return R.ok(userService.selectUserVoById(id));
    }


    /**
     * 获取封存数据列表
     *
     * @return list
     */
    @GetMapping("/getUserSealList")
    @Operation(summary = "获取封存数据列表", description = "获取封存数据列表")
    public R getUserSealList() {
        return R.ok(userService.getUserSealList());
    }

    /**
     * 通过角色名称查询角色列表
     *
     * @param roleName
     * @return 角色id
     */
    @PreAuthorize("@pms.hasPermission('sys_role_view')")
    @GetMapping("/getRoleName")
    @Operation(summary = "通过角色名称查询角色列表", description = "通过角色名称查询角色列表")
    public R getRoleName(@ParameterObject Page page, String roleName) {
        return R.ok(userService.getRoleName(page, roleName));
    }

    /**
     * 获取所有公司信息
     *
     * @return 公司信息
     */
    @PreAuthorize("@pms.hasPermission('sys_role_view')")
    @GetMapping("/getCompany")
    @Operation(summary = "获取所有公司信息", description = "获取所有公司信息")
    public R getCompany() {
        return R.ok(userService.getCompany());
    }


    /**
     * 获取所有部门公司信息通过名称模糊查询
     *
     * @return 公司信息
     */
    @PreAuthorize("@pms.hasPermission('sys_role_view')")
    @GetMapping("/getOrganizational")
    @Operation(summary = "获取所有部门公司信息通过名称模糊查询", description = "获取所有部门公司信息通过名称模糊查询")
    public R getOrganizational() {
        return R.ok(userService.getOrganizational());
    }

    /**
     * 通过公司获取部门
     *
     * @return 部门信息
     */
    @PreAuthorize("@pms.hasPermission('sys_role_view')")
    @GetMapping("/getDept")
    @Operation(summary = "通过公司获取部门", description = "通过公司获取部门")
    public R getDept(Long id) {
        return R.ok(userService.getDept(id));
    }

    /**
     * 分页查询 扣款管理
     *
     * @param page             分页对象
     * @param deductionPageDTO 参数列表
     * @return
     */
    @GetMapping("/getDeductionPage")
    @Operation(summary = "分页查询用户 扣款管理", description = "分页查询用户 扣款管理")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    public R getDeductionPage(@ParameterObject Page page, @ParameterObject DeductionPageDTO deductionPageDTO) {
        return R.ok(userService.getDeductionPage(page, deductionPageDTO));
    }

    /**
     * 扣款操作
     *
     * @param deductionDTO 参数列表
     * @return success/false
     */
    @SysLog("扣款操作")
    @PostMapping("/getDeduction")
    @Operation(summary = "扣款操作", description = "扣款操作")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R user(@Valid @RequestBody DeductionDTO deductionDTO) {
        return R.ok(userService.getDeduction(deductionDTO));
    }

    /**
     * 分页查询用户权限  账户权限列表
     *
     * @param page         参数集
     * @param userLimitDTO 查询参数列表
     * @return 用户集合
     */
    @GetMapping("/pageLimit")
    @Operation(summary = "分页查询用户权限  账户权限列表", description = "分页查询用户权限  账户权限列表")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    public R getLimitPage(@ParameterObject Page page, @ParameterObject UserLimitDTO userLimitDTO) {
        return R.ok(userService.page(page, Wrappers.<SysUser>lambdaQuery().like(StrUtil.isNotBlank(userLimitDTO.getUserAccount()), SysUser::getUserAccount, userLimitDTO.getUserAccount()).like(StrUtil.isNotBlank(userLimitDTO.getUsername()), SysUser::getUsername, userLimitDTO.getUsername()).eq(StrUtil.isNotBlank(userLimitDTO.getPhone()), SysUser::getPhone, userLimitDTO.getPhone()).eq(userLimitDTO.getRoleId() != null, SysUser::getRoleId, userLimitDTO.getRoleId()).eq(StrUtil.isNotBlank(userLimitDTO.getLockFlag()), SysUser::getLockFlag, userLimitDTO.getLockFlag())));
    }

    /**
     * 分页查询用户  钱包总览
     *
     * @param page      参数集
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @GetMapping("/getUsersWalletPage")
    @Operation(summary = "分页查询用户 钱包总览", description = "分页查询用户 钱包总览")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    public R getUsersWalletPage(@ParameterObject Page page, @ParameterObject WalletDTO walletDTO) {
        return R.ok(userService.getUsersWalletPage(page, walletDTO));
    }

    /**
     * 钱包总览导出
     *
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @SysLog("钱包总览导出")
    @ResponseExcel
    @GetMapping("/getUsersWalletExcel")
    @Operation(summary = "钱包总览导出", description = "钱包总览导出")
    public List getUsersWalletExcel(WalletDTO walletDTO) {
        return userService.getUsersWalletExcel(walletDTO);
    }

    /**
     * 现金钱包导出
     *
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @SysLog("钱包总览导出")
    @ResponseExcel
    @GetMapping("/getUsersCashExcel")
    @Operation(summary = "现金钱包导出", description = "现金钱包导出")
    public List getUsersCashExcel(WalletDTO walletDTO) {
        return userService.getUsersCashExcel(walletDTO);
    }

    /**
     * 餐补钱包导出
     *
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @SysLog("钱包总览导出")
    @ResponseExcel
    @GetMapping("/getUsersCardExcel")
    @Operation(summary = "餐补钱包导出", description = "餐补钱包导出")
    public List getUsersCardExcel(WalletDTO walletDTO) {
        return userService.getUsersCardExcel(walletDTO);
    }

    /**
     * 钱包总览  统计钱包数量
     *
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @GetMapping("/getUsersWallet")
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    @Operation(summary = "分页查询用户 钱包总览 1钱包总览  2餐补  3现金", description = "分页查询用户 钱包总览 1钱包总览  2餐补  3现金")
    public R getUsersWallet(@ParameterObject WalletDTO walletDTO) {
        return R.ok(userService.getUsersWallet(walletDTO));
    }

    /**
     * 分页查询用户  钱包餐食
     *
     * @param page      参数集
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    @GetMapping("/getUsersWalletMealPage")
    @Operation(summary = "分页查询用户 钱包餐食", description = "分页查询用户 钱包餐食")
    public R getUsersWalletMealPage(@ParameterObject Page page, @ParameterObject WalletDTO walletDTO) {
        return R.ok(userService.getUsersWalletMealPage(page, walletDTO));
    }

    /**
     * 分页查询用户  钱包现金
     *
     * @param page      参数集
     * @param walletDTO 查询参数列表
     * @return 用户集合
     */
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    @GetMapping("/getUsersWalletCashPage")
    @Operation(summary = "分页查询用户 钱包现金", description = "分页查询用户 钱包现金")
    public R getUsersWalletCashPage(@ParameterObject Page page, @ParameterObject WalletDTO walletDTO) {
        return R.ok(userService.getUsersWalletCashPage(page, walletDTO));
    }

    /**
     * 分页查询用户  账户列表
     *
     * @param page        参数集
     * @param userPageDTO 查询参数列表
     * @return 用户集合
     */
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    @GetMapping("/page")
    @Operation(summary = "分页查询用户 账户列表", description = "分页查询用户 账户列表")
    public R getUserPage(@ParameterObject Page page, @ParameterObject UserPageDTO userPageDTO) {
        return R.ok(userService.getUsersWithRolePage(page, userPageDTO));
    }

    /**
     * 分页查询用户  账号列表权限
     *
     * @param page        参数集
     * @param userPageDTO 查询参数列表
     * @return 用户集合
     */
    @PreAuthorize("@pms.hasPermission('sys_user_view')")
    @GetMapping("/getUserAuthorityPage")
    @Operation(summary = "分页查询用户  账号列表权限", description = "分页查询用户  账号列表权限")
    public R getUserAuthorityPage(@ParameterObject Page page, @ParameterObject UserPageDTO userPageDTO) {
        return R.ok(userService.getUserAuthorityPage(page, userPageDTO));
    }

    /**
     * 添加用户权限
     *
     * @param addAuthorityDTO 用户信息
     * @return success/false
     */
    @SysLog("添加用户权限")
    @PostMapping("/addAuthority")
    @PreAuthorize("@pms.hasPermission('sys_user_add')")
    @Operation(summary = "添加用户权限", description = "添加用户权限")
    public R user(@Valid @RequestBody AddAuthorityDTO addAuthorityDTO) {
        return R.ok(userService.addAuthority(addAuthorityDTO));
    }


    /**
     * 修改用户权限
     *
     * @param addAuthorityDTO 用户信息
     * @return success/false
     */
    @SysLog("修改用户权限")
    @PostMapping("/updateToAuthority")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    @Operation(summary = "修改用户权限", description = "修改用户权限")
    public R updateToAuthority(@Valid @RequestBody AddAuthorityDTO addAuthorityDTO) {
        return R.ok(userService.updateToAuthority(addAuthorityDTO));
    }

    /**
     * 删除用户权限
     *
     * @param addAuthorityDTO
     * @return success/false
     */
    @SysLog("删除用户权限")
    @PostMapping("/updateAuthority")
    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    @Operation(summary = "删除用户权限", description = "删除用户权限")
    public R updateAuthority(@RequestBody AddAuthorityDTO addAuthorityDTO) {
        return R.ok(userService.updateAuthority(addAuthorityDTO.getId()));
    }

    /**
     * 添加用户
     *
     * @param userUpdateDto 用户信息
     * @return success/false
     */
    @SysLog("添加用户")
    @PostMapping
    @Operation(summary = "添加用户", description = "添加用户")
    @PreAuthorize("@pms.hasPermission('sys_user_add')")
    public R user(@Valid @RequestBody UserAddDto userUpdateDto) {
        return R.ok(userService.saveUser(userUpdateDto));
    }


    /**
     * 冻结开启
     *
     * @param userStateDTO 用户信息
     * @return success/false
     */
    @SysLog("冻结开启")
    @PostMapping("/userState")
    @Operation(summary = "冻结开启 钱包管理 2餐补  3现金", description = "冻结开启 钱包管理 2餐补  3现金")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R user(@RequestBody UserStateDTO userStateDTO) {
        return R.ok(userService.userState(userStateDTO));
    }

    /**
     * 添加用户权限
     *
     * @param userUpdateDto 用户信息
     * @return success/false
     */
    @SysLog("添加用户权限")
    @PostMapping("/addLimit")
    @PreAuthorize("@pms.hasPermission('sys_user_add')")
    public R user(@Valid @RequestBody UserLimitAddDto userUpdateDto) {
        return R.ok(userService.saveLimitUser(userUpdateDto));
    }

    /**
     * 删除用户信息 权限和用户
     *
     * @param id ID
     * @return R
     */
    @SysLog("删除用户信息 权限和用户")
    @DeleteMapping("/userDelete")
    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    @Operation(summary = "删除用户", description = "根据ID删除用户")
    public R userDel(@RequestBody Long id) {
        return R.ok(userService.deleteUserById(id));
    }


    /**
     * 根据用户信息查询出用户类型数
     *
     * @param userPageDTO 用户信息
     * @return success/false
     */
    @SysLog("根据用户信息查询出用户类型数")
    @GetMapping("/getUserNumber")
    @Operation(summary = "账户总览", description = "账户总览")
    public R getUserNumber(@ParameterObject UserPageDTO userPageDTO) {
        return R.ok(userService.getUserNumber(userPageDTO));
    }


    /**
     * 根据用户信息导出数据
     *
     * @param userPageDTO 用户信息
     * @return success/false
     */
    @SysLog("根据用户信息导出数据")
    @GetMapping("/getUserExcel")
    @ResponseExcel
    @Operation(summary = "根据用户信息导出数据", description = "根据用户信息导出数据")
    public List getUserExcel(UserPageDTO userPageDTO) {
        return userService.getUserExcel(userPageDTO);
    }

    /**
     * 更新用户信息
     *
     * @param userUpdateDto 用户信息
     * @return R
     */
    @SysLog("更新用户信息")
    @PostMapping("/updateUser")
    @Operation(summary = "更新用户信息", description = "更新用户信息")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R updateUser(@RequestBody UserUpdateDto userUpdateDto) {
        return R.ok(userService.updateUser(userUpdateDto));
    }

    /**
     * 获取指定用户全部信息
     *
     * @return 用户信息
     */
    @Inner
    @GetMapping("/info/{username}")
    public R info(@PathVariable String username) {
        SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda()
                .eq(SysUser::getUsername, username));
        if (user == null) {
            return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
        }
        return R.ok(userService.findUserInfo(user));
    }

    /**
     * 获取当前用户全部信息
     *
     * @return 用户信息
     */
    @GetMapping(value = {"/info"})
    public R info() {
        String username = SecurityUtils.getUser().getUsername();
        SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        if (user == null) {
            return R.failed(MsgUtils.getMessage(ErrorCodes.SYS_USER_QUERY_ERROR));
        }
        return R.ok(userService.findUserInfo(user));
    }

    /**
     * 查询用户信息
     *
     * @param query 查询条件
     * @return 不为空返回用户名
     */
    @Inner(value = false)
    @GetMapping("/details/user")
    public R getDetails(@ParameterObject SysUser query) {
        SysUser sysUser = userService.getOne(Wrappers.query(query), false);
        return R.ok(sysUser == null ? null : CommonConstants.SUCCESS);
    }

    /**
     * 删除用户信息
     *
     * @param ids ID
     * @return R
     */
    @SysLog("删除用户信息")
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    @Operation(summary = "删除用户", description = "根据ID删除用户")
    public R userDel(@RequestBody Long[] ids) {
        return R.ok(userService.deleteUserByIds(ids));
    }


    /**
     * 修改个人信息 （当前用户）
     *
     * @param userDto userDto
     * @return success/false
     */
    @SysLog("修改个人信息")
    @PutMapping("/personal/edit")
    public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
        return userService.updateUserInfo(userDto);
    }

    /**
     * 修改个人密码 （当前用户）
     *
     * @param userDto 用户DTO对象，包含需要修改密码的用户信息
     * @return R 返回结果对象，包含修改密码操作的结果信息
     */
    @PutMapping("/personal/password")
    public R updatePassword(@RequestBody UserDTO userDto) {
        String username = SecurityUtils.getUser().getUsername();
        userDto.setUsername(username);
        return userService.changePassword(userDto);
    }

    /**
     * @param username 用户名称
     * @return 上级部门用户列表
     */
    @GetMapping("/ancestor/{username}")
    public R listAncestorUsers(@PathVariable String username) {
        return R.ok(userService.listAncestorUsers(username));
    }

    /**
     * 导出excel 表格
     *
     * @param userDTO 查询条件
     * @return
     */
    @ResponseExcel
    @GetMapping("/export")
    @PreAuthorize("@pms.hasPermission('sys_user_export')")
    public List export(UserDTO userDTO, Long[] ids) {
        return userService.listUser(userDTO, ids);
    }

    /**
     * 导入用户
     *
     * @param excelVOList   用户列表
     * @param bindingResult 错误信息列表
     * @return R
     */
    @PostMapping("/import")
    @PreAuthorize("@pms.hasPermission('sys_user_export')")
    public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
        return userService.importUser(excelVOList, bindingResult);
    }

    /**
     * 锁定指定用户
     *
     * @param username 用户名
     * @return R
     */
    @Inner
    @PutMapping("/lock/{username}")
    public R lockUser(@PathVariable String username) {
        return userService.lockUser(username);
    }

    /**
     * 解绑定接口
     *
     * @param type 需要解绑定的类型
     * @return R 返回结果对象，包含解绑定操作的结果信息
     */
    @PostMapping("/unbinding")
    public R unbinding(String type) {
        return userService.unbinding(type);
    }

    /**
     * 校验密码接口
     *
     * @param password 需要校验的密码
     * @return R 返回结果对象，包含校验密码操作的结果信息
     */
    @PostMapping("/check")
    public R check(String password) {
        return userService.checkPassword(SecurityUtils.getUser().getUsername(), password);
    }

    /**
     * 根据角色ID列表获取用户ID列表接口
     *
     * @param roleIdList 角色ID列表
     * @return R 返回结果对象，包含根据角色ID列表获取到的用户ID列表信息
     */
    @GetMapping("/getUserIdListByRoleIdList")
    public R<List<Long>> getUserIdListByRoleIdList(Long[] roleIdList) {
        return R.ok(userService.listUserIdByRoleIds(CollUtil.toList(roleIdList)));
    }

    /**
     * 根据部门ID列表获取用户ID列表接口
     *
     * @param deptIdList 部门ID列表
     * @return R 返回结果对象，包含根据部门ID列表获取到的用户ID列表信息
     */
    @GetMapping("/getUserIdListByDeptIdList")
    public R<List<SysUser>> getUserIdListByDeptIdList(Long[] deptIdList) {
        return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList)));
    }

    /**
     * 根据用户名获取用户列表
     *
     * @param username 用户名
     * @return 用户列表
     */
    @GetMapping("/getUserListByUserName")
    public R<List<SysUser>> getUserListByUserName(String username) {
        return R.ok(userService.list(Wrappers.<SysUser>lambdaQuery().like(SysUser::getUsername, username)));
    }

}
